// Copyright (C) joyinter
// All rights reserved.
// 
// Author : Jiang Li
// Date   : 2005-5-19

#include "stdafx.h"
#include "proccheck.h"
#include "apihelp.h"
#include "autohandle.h"

namespace JoyGuard
{

//##ModelId=44CF17BE02D9
ProcCheck::ProcCheck()
{
}
 
//##ModelId=44CF17BE02DE
ProcCheck::~ProcCheck()
{
}

//##ModelId=44CF17BE02D2
void ProcCheck::CheckProc()
{
    for(; !m_stopped; )
    {
        ApiHelp::WaitForSingleObject(m_waitEvent, m_checkDelay);
        if(m_stopped)
        {
            break;
        }

#ifdef GUARD_TIME_TEST
        SYSTEMTIME lastCheck;
        GetSystemTime(&lastCheck);
        SystemTimeToFileTime(&lastCheck, &m_lastCheck);
#endif
        PROCESSENTRY32 pe32;
        AutoHandle ProcessSnap = ApiHelp::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
        if(ProcessSnap == INVALID_HANDLE_VALUE)
        {
            continue;
        }
        
        pe32.dwSize = sizeof(pe32);
        if(!ApiHelp::Process32First(ProcessSnap, &pe32))
        {
            continue;
        }

        do
        {
            m_currProcess = ApiHelp::OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID);
            if(m_currProcess == NULL)
            {
                continue;
            }
            AutoHandle autoProc(m_currProcess);

            m_currProcessId = pe32.th32ProcessID;

#ifdef GUARD_TIME_TEST
            FILETIME createTime, exitTime, userTime, kernelTime;
            if(!::GetProcessTimes(m_currProcess, &createTime, &exitTime, &kernelTime, &userTime))
            {
                continue;
            }
            if(*(UINT64*)&createTime < *(UINT64*)&m_lastCheck)
            {
                if(*(UINT64*)&m_lastCheck - *(UINT64*)&createTime >
                    60*10000000) // 60 seconds
                {
                    //continue;
                }
            }
#endif

            AutoHandle hModuleSnap = INVALID_HANDLE_VALUE;
            hModuleSnap = ApiHelp::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, m_currProcessId);

            if(hModuleSnap == INVALID_HANDLE_VALUE)
            {
                continue;
            }
            MODULEENTRY32 me32;
            me32.dwSize = sizeof( MODULEENTRY32 );

            if(!ApiHelp::Module32First(hModuleSnap, &me32))
            {
                continue;
            }
            const char* exeName = pe32.szExeFile+strlen(pe32.szExeFile);
            for(; exeName > pe32.szExeFile; -- exeName)
            {
                if(*exeName == '\\' || *exeName == '/' || *exeName == ':')
                {
                    ++exeName;
                    break;
                }
            }
            do
            {
                try
                {
                    if(stricmp(me32.szModule, exeName) == 0)
                    {
                        OnCheck(&me32);
                        break;
                    }
                }
                catch(...)
                {
                    if(m_stopped)
                    {
                        break;
                    }
                    else if(m_error == EC_CHECK_IMAGE)
                    {
#ifdef _DEBUG
                            return;
#else
                            continue;
#endif
                    }
                }
            }
            while(ApiHelp::Module32Next(hModuleSnap, &me32));
        }
        while(ApiHelp::Process32Next(ProcessSnap, &pe32));
    }
}

//##ModelId=44CF17BE02D4
void ProcCheck::ReadMemory(void* dst, void* src, int len)
{
    CheckBase::ReadMemory(m_currProcess, (BYTE*)dst, (BYTE*)src, len);
}

} // namespace JoyGuard
